package com.th.supcom.pds.impl.service.internal.phamapply;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.carefx.framework.exception.BusinessException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.th.supcom.pds.domain.pojo.DeptVsDispensary;
import com.th.supcom.pds.domain.pojo.InpPhamApplyDetailSummary;
import com.th.supcom.pds.domain.vo.InpPhamApplyDetailVO;
import com.th.supcom.pds.impl.common.enums.AvailableEnum;
import com.th.supcom.pds.impl.common.enums.PhamExtensionTypeIdEnum;
import com.th.supcom.pds.impl.common.enums.ShiftTypeEnum;

public final class AppointDispensary
{
    /** 日志记录器. */
    public static final Logger s_logger = LoggerFactory.getLogger (AppointDispensary.class);

    private AppointDispensary ()
    {

    }

    /**
     * 分配指定药房
     * 
     * @param detailList
     * @param deptVsDispensaryList
     * @param dipsenseTypeVsDispensaryList
     * @param phamMaterialVsDispensaryList
     * @param summaryList
     */
    public static void distributeDispensary (List <InpPhamApplyDetailVO> detailList, List <DeptVsDispensary> deptVsDispensaryList,
                                             Map <String, List <DeptVsDispensary>> shiftDispensaryMap,
                                             List <DeptVsDispensary> dipsenseTypeVsDispensaryList,
                                             List <DeptVsDispensary> phamMaterialVsDispensaryList, List <InpPhamApplyDetailSummary> summaryList,
                                             boolean isNight)
    {
        // 如果当前时间对应的班次为夜班，则直接指定所有药品发送到该科室对应的夜班药房，返回结果
        if (isNight)
        {
            // 获取夜班药房
            List <DeptVsDispensary> nightDeptVsDispensaries = shiftDispensaryMap.get (ShiftTypeEnum.NightShift.getEnumCode ());
            if (CollectionUtils.isEmpty (nightDeptVsDispensaries))
            {
                s_logger.error ("没有配置夜班药房");
                throw new BusinessException ("没有配置夜班药房");
            }
            
            DeptVsDispensary nightDispensary = getPrimaryDispensary (nightDeptVsDispensaries);
            
            if (null == nightDispensary)
            {
                throw new BusinessException ("护理单元没有配置夜班药房，请在科室与药房配置关系中配置");
            }
            for (InpPhamApplyDetailVO inpPhamApplyDetailVO : detailList)
            {
                inpPhamApplyDetailVO.setApplyDispensary (nightDispensary.getDispensary ());
                inpPhamApplyDetailVO.setExecDispensary (nightDispensary.getDispensary ());
            }
            for (InpPhamApplyDetailSummary summary : summaryList)
            {
                summary.setDispensary (nightDispensary.getDispensary ());
            }
            return;
        }

        Map <String, DeptVsDispensary> dispensaryMap = getPrimayDispensaryByPhamStdCode (deptVsDispensaryList, dipsenseTypeVsDispensaryList,
                                                                                         phamMaterialVsDispensaryList, summaryList);

        // 遍历Map，根据药品的标准码确定药品的分类，进而确定药品的摆药药房
        for (InpPhamApplyDetailVO inpPhamApplyDetailVO : detailList)
        {
            inpPhamApplyDetailVO.setApplyDispensary (dispensaryMap.get (inpPhamApplyDetailVO.getPhamStdCode ()).getDispensary ());
            inpPhamApplyDetailVO.setExecDispensary (dispensaryMap.get (inpPhamApplyDetailVO.getPhamStdCode ()).getDispensary ());
        }
    }

    /**
     * 获取优先级最高的药房
     * 
     * @return
     */
    private static DeptVsDispensary getPrimaryDispensary (List <DeptVsDispensary> deptVsDispensaryList)
    {
        int first = Integer.MAX_VALUE;
        DeptVsDispensary primaryDispensary = null;
        for (DeptVsDispensary deptVsDispensary : deptVsDispensaryList)
        {
            if (first > deptVsDispensary.getPrioriyt ())
            {
                first = deptVsDispensary.getPrioriyt ();
                primaryDispensary = deptVsDispensary;
            }
        }

        return primaryDispensary;
    }

    /**
     * 根据药品编码分配药房
     * 
     * @param deptVsDispensaryList
     * @param dipsenseTypeVsDispensaryList
     * @param phamMaterialVsDispensaryList
     * @param summaryList
     * @return
     */
    private static Map <String, DeptVsDispensary> getPrimayDispensaryByPhamStdCode (List <DeptVsDispensary> deptVsDispensaryList,
                                                                                    List <DeptVsDispensary> dipsenseTypeVsDispensaryList,
                                                                                    List <DeptVsDispensary> phamMaterialVsDispensaryList,
                                                                                    List <InpPhamApplyDetailSummary> summaryList)
    {
        Map <String, List <DeptVsDispensary>> dispensaryMap = getDispensaryByPhamStdCode (phamMaterialVsDispensaryList, dipsenseTypeVsDispensaryList,
                                                                                          summaryList);
        return getDeptDispensary (deptVsDispensaryList, dispensaryMap, summaryList);
    }

    /**
     * 合并护理单元与药房的配置关系和药品与药房的配置关系*
     * 
     * @param deptVsDispensaryList
     * @param dispensaryMap
     * @return
     */
    private static Map <String, DeptVsDispensary> getDeptDispensary (List <DeptVsDispensary> deptVsDispensaryList,
                                                                     Map <String, List <DeptVsDispensary>> dispensaryMap,
                                                                     List <InpPhamApplyDetailSummary> summaryList)
    {
        Map <String, DeptVsDispensary> map = new HashMap <String, DeptVsDispensary> ();
        Map <String, DeptVsDispensary> resutMap = new HashMap <String, DeptVsDispensary> ();
        Map <String, InpPhamApplyDetailSummary> summaryDispensary = PhamApplyConvertUtils.convertPhamInfoListToMapByPhamStdCode (summaryList);
        for (DeptVsDispensary dispensary : deptVsDispensaryList)
        {
            map.put (dispensary.getDispensary (), dispensary);
        }

        for (Map.Entry <String, List <DeptVsDispensary>> entry : dispensaryMap.entrySet ())
        {
            List <DeptVsDispensary> list = entry.getValue ();
            List <DeptVsDispensary> commonList = getCommonDispensaryByNurseUnit (map, list);
            // 获取最终指定的药房
            DeptVsDispensary reustDispensary = getPrimaryDispensary (commonList);
            resutMap.put (entry.getKey (), reustDispensary);
            // 更新药品的发药药房
            InpPhamApplyDetailSummary summary = summaryDispensary.get (entry.getKey ());
            summary.setDispensary (reustDispensary.getDispensary ());
        }
        return resutMap;
    }

    /**
     * 获取护理单元和药品公共的药房
     * 
     * @return
     */
    private static List <DeptVsDispensary> getCommonDispensaryByNurseUnit (Map <String, DeptVsDispensary> map, List <DeptVsDispensary> list)
    {
        if (CollectionUtils.isEmpty (list))
        {
            throw new BusinessException ("请配置护理单元与药房的对应关系");
        }

        ArrayList <DeptVsDispensary> deptVsDispensaries = new ArrayList <DeptVsDispensary> ();
        for (DeptVsDispensary dispensary : list)
        {
            if (map.containsKey (dispensary.getDispensary ()))
            {
                deptVsDispensaries.add (map.get (dispensary.getDispensary ()));
            }
        }
        return deptVsDispensaries;
    }

    /**
     * 根据药品标准码对药房进行分组,并获取符合摆药类型和药品材质两个条件的药房
     * 
     * @return
     */
    private static Map <String, List <DeptVsDispensary>> getDispensaryByPhamStdCode (List <DeptVsDispensary> phamMaterialVsDispensaryList,
                                                                                     List <DeptVsDispensary> phamTypeVsDispensaryList,
                                                                                     List <InpPhamApplyDetailSummary> summaryList)
    {
        Map <String, List <DeptVsDispensary>> map = new HashMap <String, List <DeptVsDispensary>> ();
        Map <String, List <DeptVsDispensary>> materialMap = getDispensaryByMaterial (phamMaterialVsDispensaryList);
        Map <String, List <DeptVsDispensary>> dispenseMap = getDispensaryByDipsenseType (phamTypeVsDispensaryList);
        for (InpPhamApplyDetailSummary summary : summaryList)
        {
            // 根据材质类型获取药房
            List <DeptVsDispensary> materialList = materialMap.get (summary.getPhamMaterialType ());
            // 根据摆药类型获取药房
            List <DeptVsDispensary> dispenseList = dispenseMap.get (getPhamDispenseType (summary));
            List <DeptVsDispensary> commonList = getCommonDispensary (materialList, dispenseList);
            map.put (summary.getPhamStdCode (), commonList);
        }
        return map;
    }

    /**
     * 获取摆药类型
     * 
     * @return
     */
    private static String getPhamDispenseType (InpPhamApplyDetailSummary summary)
    {
        if (AvailableEnum.YES.getEnumCode ().equals (summary.getLargeLiquid ()))
        {
            return PhamExtensionTypeIdEnum.LargeLiquid.getEnumCode ();
        }

        if (AvailableEnum.YES.getEnumCode ().equals (summary.getOralPills ()))
        {
            return PhamExtensionTypeIdEnum.OralPills.getEnumCode ();
        }

        return null;
    }

    /**
     * 根据药房材质获取药房
     * 
     * @return
     */
    private static Map <String, List <DeptVsDispensary>> getDispensaryByMaterial (List <DeptVsDispensary> phamMaterialVsDispensaryList)
    {
        Map <String, List <DeptVsDispensary>> map = new HashMap <String, List <DeptVsDispensary>> ();
        for (DeptVsDispensary dispensary : phamMaterialVsDispensaryList)
        {
            List <DeptVsDispensary> list = null;
            if (map.containsKey (dispensary.getPhamMaterialType ()))
            {
                list = map.get (dispensary.getPhamMaterialType ());
            }
            else
            {
                list = new ArrayList <DeptVsDispensary> ();
            }
            list.add (dispensary);
            map.put (dispensary.getPhamMaterialType (), list);
        }
        return map;
    }

    /**
     * 根据摆药类型获取药房
     * 
     * @return
     */
    private static Map <String, List <DeptVsDispensary>> getDispensaryByDipsenseType (List <DeptVsDispensary> phamTypeVsDispensaryList)
    {
        Map <String, List <DeptVsDispensary>> map = new HashMap <String, List <DeptVsDispensary>> ();
        for (DeptVsDispensary dispensary : phamTypeVsDispensaryList)
        {
            List <DeptVsDispensary> list = null;
            if (map.containsKey (dispensary.getPhamDispenseType ()))
            {
                list = map.get (dispensary.getPhamDispenseType ());
            }
            else
            {
                list = new ArrayList <DeptVsDispensary> ();
            }
            list.add (dispensary);
            map.put (dispensary.getPhamDispenseType (), list);
        }
        return map;
    }

    /**
     * 获取公共的药房
     * 
     * @return
     */
    private static List <DeptVsDispensary> getCommonDispensary (List <DeptVsDispensary> firstList, List <DeptVsDispensary> secondList)
    {
        if (CollectionUtils.isEmpty (firstList))
        {
            return secondList;
        }

        if (CollectionUtils.isEmpty (secondList))
        {
            return firstList;
        }

        Map <String, DeptVsDispensary> map = new HashMap <String, DeptVsDispensary> ();
        List <DeptVsDispensary> commonDispensayList = new ArrayList <DeptVsDispensary> ();
        for (DeptVsDispensary dispensary : firstList)
        {
            map.put (dispensary.getDispensary (), dispensary);
        }

        for (DeptVsDispensary dispensary : secondList)
        {
            if (map.containsKey (dispensary.getDispensary ()))
            {
                commonDispensayList.add (dispensary);
            }
        }

        return commonDispensayList;
    }

    /** 公司版权信息. */
    public static final String copyright = "Copyright 2014, XuNuo Corporation";

    /** 提交路径. */
    public static final String SCC_BRANCH = "$URL$";

    /** 提交日期. */
    public static final String SCC_LAST_MODIFICATION_DATE = "$Date$";

    /** 最终修改人员. */
    public static final String SCC_LAST_MODIFIER_NAME = "$Author$";

    /** 最终版本号. */
    public static final String SCC_REVISION = "$Revision$";
}
